// =============================================================
// CMIMEClientCallback class
// ---------------------------------------
// Author : Woo-Hyun Kim
// Email : woorung@icu.ac.kr or woorung@nhncorp.com
// Date : Apr. 17, 2008
// =============================================================
#include "CMIMEClientCallback.h"
//---------------------------------------------------------------------------------------------
CMIMEClientCallback::CMIMEClientCallback() : CMIMECallback()
{
}

CMIMEClientCallback::~CMIMEClientCallback()
{
}

/*
 * \brief We should return NULL without setting soap->error if we don't want to use the streaming callback for this MIME attachment
 * \brief The handle contains the non-NULL __ptr field value of xop__Include which should have been set in the application 
 * \brief The return value of this function will be passed on to the fmimeread and fmimereadclose callbacks
 * \brief The return value will not affect the value of the __ptr field.
 *
 * \param handle "fd" will be passed from __ptr of open() in CFileProxy.cpp
 */
void *CMIMEClientCallback::read_open(struct soap *soap, void *handle, const char *id, const char *type, const char *description)
{ 
#ifdef DEBUG
	cerr << "handle(local file to read) = " << (char *)handle << endl;
	cerr << "id(remote file to save) = " << (char *)id << endl;
#endif

	FILE *fd = NULL;
	const char *file = (char *)handle;

	fd = (FILE *)fopen64((char *)file, "rb");
	if(!fd) {
		fclose(fd);

		string err_msg = "ERROR : cannot open file ";
		err_msg += soap->endpoint;
		err_msg += ":";
		err_msg += file;

		soap->error = soap_receiver_fault(soap, (char *)err_msg.c_str(), NULL);
		soap->errnum = errno;
		return NULL;
	}

	return (void*)fd;
}

size_t CMIMEClientCallback::read(struct soap *soap, void *handle, char *buf, size_t len)
{
	FILE *fd = NULL;
	fd = (FILE *)handle;

	return fread(buf, 1, len, fd);
}

void CMIMEClientCallback::read_close(struct soap *soap, void *handle)
{
	FILE *fd = NULL;
	fd = (FILE *)handle;

	fclose(fd);
}

void *CMIMEClientCallback::write_open(struct soap *soap, void *unused_handle, const char *id, const char *type, const char *description, enum soap_mime_encoding encoding)
{ 
#ifdef DEBUG
	cerr << "[client callback]handle(remote file to read) = " << (char *)handle << endl;
	cerr << "[client callback]id(target file to save) = " << (char *)id << endl;
#endif

	const char *file = (char *)id;
	FILE *fd = (FILE *)fopen64((char *)file, "w+b");
	if(!fd) {
		string err_msg = "cannot save data to the file ";
		err_msg += file;
		soap->error = soap_receiver_fault(soap, (char *)err_msg.c_str(), NULL);
		soap->errnum = errno;
		return NULL;
	}

	// change access mode
	CFile file_util;
	if(file_util.change_mode(file, 0777)<0) {
		string err_msg = "cannot change the access mode of the file ";
		err_msg += file;
		soap->error = soap_receiver_fault(soap, (char *)err_msg.c_str(), NULL);
		soap->errnum = errno;
		return NULL;
	}

	return (void*)fd;
}

int CMIMEClientCallback::write(struct soap *soap, void *handle, const char *buf, size_t len)
{ 
	FILE *fd = (FILE*)handle;

	while (len) { 
		size_t nwritten = fwrite(buf, 1, len, fd);
		if(!nwritten) { 
			soap->errnum = errno;
			return SOAP_EOF;
		}

		len -= nwritten;
		buf += nwritten;
	}

	return SOAP_OK;
}

void CMIMEClientCallback::write_close(struct soap *soap, void *handle)
{ 
	fclose((FILE*)handle);
}
